home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / qsort.mor < prev    next >
Text File  |  1995-03-23  |  7KB  |  160 lines

  1. Article 1794 of comp.sys.handhelds:
  2. Path: en.ecn.purdue.edu!pur-ee!mentor.cc.purdue.edu!purdue!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!jarthur!nntp-server.caltech.edu!piglet!madler
  3. From: madler@piglet.caltech.edu (Mark Adler)
  4. Newsgroups: comp.sys.handhelds
  5. Subject: My last post on sorting (sure) for the HP-48SX
  6. Message-ID: <1990Apr11.045126.5737@laguna.ccsf.caltech.edu>
  7. Date: 11 Apr 90 04:51:26 GMT
  8. Sender: news@laguna.ccsf.caltech.edu
  9. Organization: California Institute of Technology, Pasadena
  10. Lines: 146
  11.  
  12.  
  13. Here posted are somewhat improved versions of SORT and QPART.  These
  14. represent about a 2% increase in speed from the previous version (I
  15. couldn't resist even such a trivial improvement).  The change was
  16. simply to test the size of the list before calling QPART, both from
  17. SORT, and from the two places in QPART itself.  The comments are also
  18. a little more complete.  Enjoy.
  19.  
  20. Mark Adler
  21. madler@tybalt.caltech.edu
  22.  
  23.  
  24. %%HP: T(3)A(R)F(.);
  25. @ SORT crc #10B7h length 141
  26. @
  27. @ by Mark Adler  10 Apr 1990
  28. @
  29. @ Use QPART to do a quicksort up to subfiles of length 20, and then do
  30. @ one pass of an insertion sort to sort the subfiles.  See the comments
  31. @ in QPART.
  32. @
  33. @ The sort will be fastest if the list being sorted was recalled from a
  34. @ global variable.  This avoids garbage collection on the objects in
  35. @ the list when they are on the stack.  It will also speed the sort to
  36. @ disable last args with a "-55 SF".
  37. @
  38. @ To sort objects other than reals or strings, change the ">" in
  39. @ "PICK >" to the appropriate code and modify QPART in the same way
  40. @ (see the comments in QPART).
  41. @
  42. \<< OBJ\-> DUP \-> n                    @ put list on stack
  43.   \<< 
  44.     @
  45.     @ if size > 20, do quicksort
  46.     @
  47.     IF DUP 20 > THEN 2 QPART n END      @ partition is [1] to [n]
  48.     @
  49.     @ do insertion sort on what remains
  50.     @
  51.     2 SWAP FOR j                        @ starting with j=2, insert [j]
  52.       j ROLL j 2 +                      @ [1]..[j-1] is sorted, get [j]
  53.       WHILE DUP2 PICK > REPEAT 1 - END  @ find where [j] goes
  54.       2 - ROLLD                         @ put [j] there
  55.     NEXT
  56.     n \->LIST                           @ convert back to list
  57.   \>>
  58. \>>
  59.  
  60.  
  61. %%HP: T(3)A(R)F(.);
  62. @ QPART crc #7BCCh length 419.5
  63. @
  64. @ by Mark Adler  10 Apr 1990
  65. @ Given a partition of the stack, pick an entry in the partition and
  66. @ split the partition into two partitions such that all the entries in
  67. @ the first one are less than the entry picked, and all the entries in
  68. @ the second one are greater than the entry picked, and the entry is
  69. @ placed between them.  Then call this routine recursively for each of
  70. @ those partitions, unless the partition is 20 entries or less.  A
  71. @ final pass of an insertion sort should be done to sort the remaining
  72. @ short partitions.  The value of 20 was determined experimentally on
  73. @ test cases of lists of random reals.
  74. @
  75. @ The entry for partitioning is picked using the median method, which
  76. @ picks the median value of the entries at the beginning, middle, and
  77. @ end of the list.  This makes the sort fast for already sorted lists,
  78. @ and greatly reduces the probability of the sort taking order n^2
  79. @ time.  It also reduces the total number of comparisons, speeding the
  80. @ sort somewhat.  Most importantly, an additional step of sorting the
  81. @ first and last elements of the list (which adds one compare) allows
  82. @ the inner loops of the algorithm to not have to check for the bounds
  83. @ of the partition.  This special-purpose three element sort does not
  84. @ cost extra, since the outer two elements would have to have been
  85. @ compared and swapped anyway if they were in the wrong place.
  86. @
  87. @ The arguments to QPART are two integers specifying the stack levels
  88. @ to partition.  The arguments refer to the stack after the arguments
  89. @ are removed from the stack.  The integer in the first level minus 1
  90. @ is the starting level, and the integer in level 2 is the ending level
  91. @ to partition.  So, for example, to partition the stack levels 1
  92. @ through n, the calling sequence would be "n 2 QPART".  Since QPART
  93. @ does not check the partition size on entry, the calling routine
  94. @ should do that and avoid calling QPART for sizes of 20 or less.
  95. @
  96. @ The algorithm can be modified to sort objects besides reals and
  97. @ strings by replacing the ">" in the "IF DUP2 >"'s and in the "PICK >"
  98. @ and replacing the "<" in the "PICK <" with the appropriate code for
  99. @ the object.  The routine can be generalized (at a speed penalty) by
  100. @ replacing said ">"'s with "GT" and the said "<" with "SWAP GT" and
  101. @ defining a function "GT" that does the job before doing the sort.
  102. @
  103. \<<
  104.   @ sort the partition of the stack from level l-1 to level r (after
  105.   @  l and r are pulled off of the stack).
  106.   \-> r l \<<
  107.     @
  108.     @ sort [l-1], [m], [r] so that [l-1] >= [m] >= [r] where m points
  109.     @  to the middle of the partition.
  110.     @
  111.     r l + 2 / FLOOR ROLL                @ get [m]
  112.     l ROLL                              @ get [l-1]
  113.     IF DUP2 > THEN SWAP END             @ sort [m], [l-1]
  114.     l ROLLD r ROLL                      @ put back new [l-1]; get [r]
  115.     IF DUP2 > THEN                      @ if [r], [m] sorted,
  116.       r                                 @  then just put [r] back
  117.     ELSE
  118.       SWAP r ROLLD l ROLL               @ else sort [r], [m]; get [l-1]
  119.       IF DUP2 > THEN SWAP END           @  and re-sort [m] and [l-1]
  120.       l                                 @ put [l-1] back
  121.     END
  122.     ROLLD
  123.     @
  124.     @ start sorting inside [l-1], [r] since [l-1] and [r] are already
  125.     @ sorted.  put [m] in list so that [i] >= [m] >= [j] for i < j.
  126.     @
  127.     r 3 + SWAP                          @ i = l-1 (loop begins "1 +")
  128.     l 3 +                               @ j = r-1 (since m pulled out)
  129.     WHILE                               @ stack is i+4,[m],j+4,list...
  130.       WHILE 1 + DUP2 PICK < REPEAT END  @ now [m] >= [i]
  131.       SWAP ROT
  132.       WHILE 1 - DUP2 PICK > REPEAT END  @ now [j] >= [m]
  133.       ROT DUP2 >                        @ until j <= i
  134.     REPEAT                              @ stack is i+4,j+4,[m],list...
  135.       DUP2 ROLL OVER ROLL               @ swap [i], [j]
  136.       4 PICK 1 + ROLLD OVER ROLLD
  137.       4 ROLLD SWAP DROP                 @ stack is i+4,[m],j+4,list...
  138.     END
  139.     DROP 2 - SWAP OVER ROLLD            @ put [m] after [j]
  140.     @
  141.     @ sort the partitions [j+2..r] and [l-1..j] by calling this program
  142.     @  recursively, but only if the partition has length > 20.  The
  143.     @  stack is j+2,list...
  144.     @
  145.     IF r DUP2 - -18 < THEN              @ check top partition
  146.       SWAP DUP 'r' STO 1 + QPART r      @ save j+2 in r
  147.     ELSE
  148.       DROP
  149.     END                                 @ j+2 left on stack
  150.     IF 2 - l DUP2 - 18 > THEN           @ check bottom partition
  151.       QPART
  152.     ELSE
  153.       DROP2
  154.     END                                 @ leave the list on the stack
  155.   \>>
  156. \>>
  157.  
  158.  
  159.